#region Using directives
using System;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;
using System.IO;
using SharpWind.Helpers;
using Microsoft.DirectX;
using SharpWind.Math;
using Texture = SharpWind.Resources.Textures.Texture;
#endregion

namespace SharpWind.Resources.Meshes
{
	public class Mesh : Resource
	{
		#region Fields

		private Material[] materials = null;

		private Texture[] textures = null;

		private Direct3D.Mesh dxMesh = null;

		#endregion

		#region Methods

		internal override bool Load( string name )
		{
			if( string.IsNullOrEmpty( name ) )
			{
				throw new ArgumentNullException( "name" );
			}

			GraphicsStream adjacency;
			ExtendedMaterial[] materials;
			this.dxMesh = Direct3D.Mesh.FromFile( Path.Combine( Directories.Meshes, name ), MeshFlags.Managed,
												  Engine.Instance.Graphics.Device, out adjacency, out materials );
		
			if( ( dxMesh.VertexFormat & VertexFormats.Normal ) != VertexFormats.Normal )
			{
				Direct3D.Mesh temp = this.dxMesh.Clone( this.dxMesh.Options.Value,
														this.dxMesh.VertexFormat | VertexFormats.PositionNormal | VertexFormats.Texture1,
														Engine.Instance.Graphics.Device );
				temp.ComputeNormals();
				
				this.dxMesh = temp;
			}

			int[] outputAdjacency = new int[this.dxMesh.NumberFaces * 3];
			this.dxMesh.GenerateAdjacency( MathHelper.Epsilon, outputAdjacency );
			this.dxMesh.OptimizeInPlace( MeshFlags.OptimizeAttributeSort, outputAdjacency );

			this.materials = new Material[this.dxMesh.NumberAttributes];
			this.textures  = new Texture[this.dxMesh.NumberAttributes];
		
			for( int i = 0; i < this.dxMesh.NumberAttributes; i++ )
			{
				this.materials[i] = materials[i].Material3D;
				this.materials[i].AmbientColor = this.materials[i].DiffuseColor;

				if( string.IsNullOrEmpty( materials[i].TextureFilename ) )
				{
					this.textures[i] = null;
				}
				else
				{
					this.textures[i] = Engine.Instance.Textures.Load( materials[i].TextureFilename );
				}
			}

			return true;
		}

		#endregion

		#region Properties

		internal Direct3D.Mesh DxMesh
		{
			get
			{
				return this.dxMesh;
			}
			set
			{
				this.dxMesh = value;
			}
		}

		internal Direct3D.Material[] Materials
		{
			get
			{
				return this.materials;
			}
		}

		internal Texture[] Textures
		{
			get
			{
				return this.textures;
			}
		}

		#endregion
	}
}
